<script lang="ts" setup>
import type { AppTypeProps, MenuTypeProps } from '@/types';

import { computed, onMounted, onUnmounted, ref, watch } from 'vue';
// import { type ComponentInternalInstance, getCurrentInstance } from 'vue';

import { preferences } from '@/lib/preferences';
import { Icon } from '@/components/core/icon';

import { useNetwork, useTitle } from '@vueuse/core';
import {
  ElCalendar,
  ElDropdown,
  ElDropdownItem,
  ElDropdownMenu,
  ElMessage,
} from 'element-plus';

import App from '@/components/web-os/App.vue';
import Dock from '@/components/web-os/Dock.vue';
import Widget from '@/components/web-os/Widget.vue';
import AppModel, { appList } from '@/model/app';
import { useAppStore, useUserStore } from '@/store';

defineOptions({
  name: 'DeskTop',
});
const emits = defineEmits(['launchpad', 'lockScreen', 'logout', 'shutdown']);
const { isOnline } = useNetwork();
// const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const appStore = useAppStore();
const userStore = useUserStore();
const isCalendarShow = ref(false);
const nowDate = ref(new Date());
const rightMenuVisible = ref(false);
const rightMenuLeft = ref(0);
const rightMenuTop = ref(0);
const userName = ref('');
const menu = ref<MenuTypeProps[]>([]);
const timeString = ref('');
const deskTopAppList = ref<AppTypeProps[]>([]);

const isWidgetShow = ref(false);
const bodyElRef = ref();
const dockElRef = ref();
const float = computed(() => {
  return appStore.setting.float;
});

/**
 * @description: 隐藏所有弹出的控制器
 */
const hideAllController = () => {
  rightMenuVisible.value = false;
  isCalendarShow.value = false;
  dockElRef.value?.hideAllController();
};
/**
 * @description: 锁定屏幕
 */
const lockScreen = () => {
  emits('lockScreen');
};
/**
 * 刷新
 */
const refresh = () => {
  location.reload();
};
/**
 * @description: 注销登录
 */
const logout = () => {
  emits('logout');
};
/**
 * @description: 打开指定key的应用
 */
const openAppByKey = (key: string) => {
  appStore.openAppByKey(key);
};

/**
 * @description: 打开右键菜单
 */
const openMenu = (e: MouseEvent) => {
  const menuMinWidth = 105;
  const offsetLeft = bodyElRef.value?.getBoundingClientRect().left; // container margin left
  const offsetWidth = bodyElRef.value?.offsetWidth; // container width
  const maxLeft = offsetWidth - menuMinWidth; // left boundary
  const left = e.clientX - offsetLeft; // margin right

  rightMenuLeft.value = left > maxLeft ? maxLeft : left;

  rightMenuTop.value = e.clientY - 30;
  rightMenuVisible.value = true;
};
/**
 * @description: 显示或隐藏日历
 */
const showOrHideCalendar = () => {
  isCalendarShow.value = !isCalendarShow.value;
};
/**
 * @description: 显示或隐藏网络
 */
const showNetwork = () => {
  appStore.openAppByKey('system_network');
};
const showOrHideWidget = () => {
  isWidgetShow.value = !isWidgetShow.value;
  ElMessage({
    message: isWidgetShow.value
      ? '显示桌面小部件（开发中）'
      : '隐藏桌面小部件（开发中）',
    type: 'success',
  });
};
/**
 * @description: 关机
 */
const shutdown = () => {
  emits('shutdown');
};

const date = ref(new Date());
const currentDate = computed(() => {
  return `${date.value.getMonth() + 1}月${date.value.getDate()}日`;
});
const currentDay = computed(() => {
  const days = [
    '星期日',
    '星期一',
    '星期二',
    '星期三',
    '星期四',
    '星期五',
    '星期六',
  ];
  return days[date.value.getDay()];
});

/**
 * @description: 打开时间计时器
 */
let timer: number | undefined;
const startTimer = () => {
  timer = window.setInterval(() => {
    const now = new Date();
    const hour = now.getHours().toString().padStart(2, '0');
    const minute = now.getMinutes().toString().padStart(2, '0');
    const second = now.getSeconds().toString().padStart(2, '0');
    timeString.value = `${hour}:${minute}:${second}`;
  }, 1000);
};
const title = preferences.app.name;
onMounted(() => {
  userName.value = userStore.userInfo?.username || 'web-os';
  deskTopAppList.value = AppModel.allAppList; // proxy?.$tool.getDeskTopApp();
  startTimer();
  appStore.getDockAppList();
});

onUnmounted(() => {
  timer && window.clearInterval(timer);
  timer = undefined;
});

watch(
  () => appStore.launchpad,
  (val) => {
    emits('launchpad', val);
  },
);

watch(
  () => appStore.nowApp,
  (val) => {
    menu.value = val ? (val.menu as MenuTypeProps[]) : [];
    if (val && val.title) {
      useTitle(`${val.title} - ${preferences?.app?.name ?? 'web-os'}`);
    } else {
      useTitle(preferences?.app?.name ?? 'web-os');
    }
  },
  { deep: true },
);
watch(
  () => appList.value,
  (val) => {
    deskTopAppList.value = val;
  },
  { deep: true },
);
</script>
<template>
  <div ref="bodyElRef" class="desktop">
    <div class="top">
      <ElDropdown popper-class="top-dropdown-menu" trigger="click">
        <div class="logo">
          <b>{{ title || 'web-os' }}</b>
        </div>
        <template #dropdown>
          <ElDropdownMenu>
            <ElDropdownItem @click="openAppByKey('system_about')">
              <div>关于 web-os WebUI</div>
            </ElDropdownItem>
            <ElDropdownItem divided @click="openAppByKey('work_connect')">
              <div>系统连接...</div>
            </ElDropdownItem>
            <ElDropdownItem divided @click="openAppByKey('system_setting')">
              <div>系统偏好设置...</div>
            </ElDropdownItem>
            <ElDropdownItem divided @click="openAppByKey('system_task')">
              <div>强制退出...</div>
            </ElDropdownItem>
            <ElDropdownItem @click="shutdown">
              <div>重启服务器...</div>
            </ElDropdownItem>
            <ElDropdownItem divided @click="lockScreen">
              <div>锁定屏幕...</div>
            </ElDropdownItem>
            <ElDropdownItem @click="logout">
              <div>退出登录 {{ userName }}...</div>
            </ElDropdownItem>
          </ElDropdownMenu>
        </template>
      </ElDropdown>
      <div v-for="item in menu" :key="item.value" class="menu">
        <ElDropdown placement="bottom-start" trigger="click">
          <div class="item">{{ item.title }}</div>
          <template #dropdown>
            <ElDropdownMenu>
              <template v-for="subItem in item.sub" :key="subItem.value">
                <ElDropdownItem v-if="subItem.isLine" class="line" />
                <ElDropdownItem
                  v-else
                  @click="appStore.openMenu(`${subItem.key}`)"
                >
                  <div>{{ subItem.title }}</div>
                </ElDropdownItem>
              </template>
            </ElDropdownMenu>
          </template>
        </ElDropdown>
      </div>
      <div class="space"></div>
      <div class="status">
        <div class="network">
          <Icon
            :icon="
              isOnline
                ? `mdi:access-point-network`
                : `mdi:access-point-network-off`
            "
            :title="isOnline ? '在线' : '离线'"
            class="iconfont size-4"
            @click="showNetwork"
          />
        </div>
        <div class="datetime" @click.self="showOrHideCalendar">
          {{ currentDate }} {{ currentDay }} {{ timeString }}
          <transition key="calendar">
            <ElCalendar v-if="isCalendarShow" v-model="nowDate" />
          </transition>
        </div>

        <div class="widget">
          <Icon
            :icon="isWidgetShow ? `mdi:widgets-outline` : `mdi:widgets`"
            class="iconfont size-4"
            title="小组件"
            @click="showOrHideWidget"
          />
        </div>
      </div>
    </div>
    <div
      class="body"
      @click.stop="hideAllController()"
      @contextmenu.prevent.self="
        hideAllController();
        openMenu($event);
      "
    >
      <div :class="float">
        <div class="desktop-app">
          <template v-for="item in deskTopAppList" :key="item.key">
            <div
              v-if="!item.hideInDesktop"
              class="app-item"
              @dblclick="appStore.openApp(item)"
            >
              <div class="icon">
                <i
                  v-if="item.iconType === 'icon'"
                  :style="{
                    backgroundColor: item.iconBgColor,
                    background: item.iconBgImage,
                    color: item.iconColor,
                  }"
                  class="iconfont"
                >
                  <Icon :icon="item.icon" class="size-8" />
                </i>
                <i
                  v-else
                  :class="item.icon"
                  :style="{
                    backgroundColor: item.iconBgColor,
                    color: item.iconColor,
                  }"
                  class="iconfont"
                ></i>
              </div>
              <div class="title">{{ item.title }}</div>
            </div>
          </template>
        </div>
      </div>
      <transition-group>
        <template v-for="item in appStore.openAppList" :key="item.pid">
          <App
            v-if="!item.outLink"
            v-show="!item.hide"
            :key="item.pid"
            :app="item"
            :pid="item.pid"
          />
        </template>
      </transition-group>
      <transition key="menu">
        <div
          v-show="rightMenuVisible"
          :style="{ left: `${rightMenuLeft}px`, top: `${rightMenuTop}px` }"
          class="contextmenu"
        >
          <div @click="refresh">刷新...</div>
          <hr />
          <div @click="openAppByKey('system_setting')">系统偏好设置...</div>
          <div @click="openAppByKey('system_app_manager')">图标管理...</div>
          <div @click="openAppByKey('system_task')">强制退出...</div>
          <hr />
          <div @click="lockScreen">锁定屏幕...</div>
          <div @click="openAppByKey('system_about')">关于我们...</div>
        </div>
      </transition>
      <transition-group tag="div">
        <div v-show="isWidgetShow" key="widget">
          <template v-for="item in appStore.openWidgetList" :key="item.pid">
            <Widget
              v-if="!item.outLink"
              v-show="!item.hide"
              :key="item.pid"
              :app="item"
            />
          </template>
        </div>
      </transition-group>
    </div>
    <Dock ref="dockElRef" />
  </div>
</template>
<style lang="scss">
@import url('./css/DeskTop.scss');
</style>
